package cn.tedu.charging.order.service;

import cn.tedu.charging.common.pojo.entity.ProgressEntity;
import cn.tedu.charging.common.pojo.message.ChargingCheckResultMessage;
import cn.tedu.charging.common.pojo.message.ChargingProgressMsg;
import cn.tedu.charging.common.pojo.message.DelayCheckMessage;
import cn.tedu.charging.common.pojo.message.ProgressData;
import cn.tedu.charging.common.pojo.param.ProgressCostParam;
import cn.tedu.charging.common.pojo.po.ChargingBillFailPO;
import cn.tedu.charging.common.pojo.po.ChargingBillSuccessPO;
import cn.tedu.charging.common.pojo.vo.ProgressCostVO;
import cn.tedu.charging.common.protocol.JsonResult;
import cn.tedu.charging.common.protocol.WebSocketMessage;
import cn.tedu.charging.common.utils.SnowflakeIdGenerator;
import cn.tedu.charging.order.feign.CostClient;
import cn.tedu.charging.order.repository.FailBillRepo;
import cn.tedu.charging.order.repository.ProgressEntityRepo;
import cn.tedu.charging.order.repository.SuccessBillRepo;
import cn.tedu.charging.order.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service
@Slf4j
public class OrderConsumerServiceImpl implements OrderConsumerService {
    @Autowired
    private SuccessBillRepo successBillRepo;
    @Autowired
    private FailBillRepo failBillRepo;
    @Autowired
    private WebSocketServer webSocketServer;
    @Autowired
    private CostClient costClient;
    @Autowired
    private ProgressEntityRepo progressEntityRepo;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private SnowflakeIdGenerator snowflakeIdGenerator = new SnowflakeIdGenerator();

    @Override
    public void handleCheckResult(ChargingCheckResultMessage msg) {
        // 1. 利用msg中的orderNo（bill_id），读取success和fail表中是否存在数据，判断本次是否可增
        log.debug("检查充电结果入参：{}", msg);
        String billId = msg.getOrderNo();
        boolean exist = checkExists(billId);
        // 2. 判断是否可增，true继续，根据msg中result true-success false-fail
        if (exist) {
            log.debug("订单已存在：{}", billId);
            return;
        } else {
            log.debug("订单不存在：{}", billId);
            Boolean result = msg.getResult();
            if (result) {
                // ToDo 组织一个ChargingBillSuccessPO
                log.debug("自检反馈成功：{}", billId);
                saveSuccess(msg);
            } else {
                // ToDO 组织一个ChargingBillFailPO
                log.debug("自检反馈失败：{}", billId);
                saveFail(msg.getOrderNo(), msg.getUserId());
                // 给用户发送一个消息，告知前端。当前扫码下单失败，重新换枪，考虑用户体验，可以送一张优惠券[短连接]
                WebSocketMessage<String> wsMsg = new WebSocketMessage<>();
                wsMsg.setState(1);
                wsMsg.setMessage("A对不起，扫码下单失败，请还枪，给您赠送一张优惠券，前往该链接领取：http://youhuiquan.com");
                webSocketServer.pushMsg(wsMsg, msg.getUserId());
            }
        }
    }

    @Override
    public void handleDelayResult(DelayCheckMessage msg) {
        log.debug("检查充电结果入参：{}", msg);
        // 1. 利用参数中orderNo 读取成功或失败
        String billId = msg.getOrderNo();
        boolean exists = checkExists(billId);
        // 2. 如果成功了或者失败了 什么都不做结束
        if (exists) {
            log.debug("订单已存在：{}", billId);
            return;
        } else {
            log.debug("订单不存在：{}", billId);
            saveFail(billId, msg.getUserId());
            // 给用户发送一个消息，告知前端。当前扫码下单失败，重新换枪，考虑用户体验，可以送一张优惠券[短连接]
            WebSocketMessage<String> wsMsg = new WebSocketMessage<>();
            wsMsg.setState(1);
            wsMsg.setMessage("A对不起，扫码下单失败，请还枪，给您赠送一张优惠券，前往该链接领取：http://youhuiquan.com");
            webSocketServer.pushMsg(wsMsg, msg.getUserId());
        }
        // 3. 如果没有成功也没有失败，按照失败处理【复用】
    }

    @Override
    public void handleChargingProgress(ChargingProgressMsg msg) {
        log.debug("充电进度入参：{}", msg);
        // 1. 利用参数orderNo,userId,stationId,gunId,pileId,capacity 调用计价获取累计金额
        ProgressCostParam param = new ProgressCostParam();
        BeanUtils.copyProperties(msg, param);
        ProgressCostVO cost = costClient.calculateBill(param).getData();
        // 2. 组织本次充电记录es的po对象，写入es，保存历史充电日志
        ProgressEntity entity = new ProgressEntity();
        BeanUtils.copyProperties(msg, entity);
        // 补充两个属性 id totalCost
        entity.setId(snowflakeIdGenerator.nextId() + "");
        entity.setTotalCost(cost.getTotalCost());
        progressEntityRepo.save(entity);
        // 3. 根据设备同步的信息属性isFull，判断是否结束充电
        Boolean isFull = msg.getIsFull();
        if (isFull) {
            WebSocketMessage<String> wsMsg = new WebSocketMessage<>();
            wsMsg.setState(1);
            wsMsg.setMessage("A充电结束，感谢使用，请还枪支付");
            webSocketServer.pushMsg(wsMsg, msg.getUserId());
        } else {
            WebSocketMessage<ProgressData> wsMsg = new WebSocketMessage<>();
            wsMsg.setState(3);
            ProgressData data = new ProgressData();
            // 缓存进度值
            String capacityKey = "charging:capacity:total"+msg.getOrderNo();
            stringRedisTemplate.boundValueOps(capacityKey).increment(msg.getChargingCapacity());
            // 单次度数
//            data.setChargingCapacity(msg.getChargingCapacity());
            data.setChargingCapacity(Double.parseDouble(stringRedisTemplate.boundValueOps(capacityKey).get()));  // 测试进度变化
            data.setTotalCost(cost.getTotalCost());
            data.setOneElectricityCost(cost.getPowerFee());
            // 填补测试数据
            data.setHours(10);
            data.setMinutes(10);
            data.setSeconds(10);
            data.setTotalCapacity(100.00);
            // 当前消息 没有计算时间 依据
            wsMsg.setData(data);
            webSocketServer.pushMsg(wsMsg, msg.getUserId());

        }

    }

    private void saveFail(String orderNo, Integer userId) {
        ChargingBillFailPO po = new ChargingBillFailPO();
        // 只补充核心的，能补充的数据
        po.setBillId(orderNo);
        po.setUserId(userId);
        // 创建时间，更新时间
        po.setCreateTime(new Date());
        po.setUpdateTime(new Date());
        failBillRepo.save(po);
    }

    private void saveSuccess(ChargingCheckResultMessage msg) {
        ChargingBillSuccessPO po = new ChargingBillSuccessPO();
        // 只补充核心的，能补充的数据
        po.setBillId(msg.getOrderNo());
        po.setUserId(msg.getUserId());
        po.setBillStatus(1);
        // 创建时间，更新时间
        po.setCreateTime(new Date());
        po.setUpdateTime(new Date());
        successBillRepo.save(po);
    }

    private boolean checkExists(String billId) {
        // select count(0) from charging_bill_success where bill_id = ?
        Long countSuccess = successBillRepo.countByBillId(billId);
        // select count(0) from charging_bill_fail where bill_id = ?
        Long countFail = failBillRepo.countByBillId(billId);
        if (countFail > 0 || countSuccess > 0)
            return true;
        return false;
    }

}
